home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
FishMarket 1.0
/
FishMarket v1.0.iso
/
fishies
/
076-100
/
disk_084
/
pipehandler
/
pipedir.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-05-06
|
12KB
|
424 lines
/****************************************************************************
** File: pipedir.c
** Program: pipe-handler - an AmigaDOS handler for named pipes
** Version: 1.2
** Author: Ed Puckett qix@mit-oz
**
** Copyright 1987 by EpAc Software. All Rights Reserved.
**
** History: 05-Jan-87 Original Version (1.0)
** 07-Feb-87 Added modifications for allowing shared locks
** on individual pipes.
** 12-Feb-87 Added PipeParentDir.
** 12-Feb-87 Fixed bug in PipeLock(): previously ignored
** lock passed in packet. Bug uncovered when
** pipes became lockable, and thus assignable.
** 27-Mar-87 Added PipeDupLock(). This was missing
** in the original version!
*/
#include <libraries/dos.h>
#include <libraries/dosextens.h>
#include <libraries/filehandler.h>
#include <exec/exec.h>
#include "pipelists.h"
#include "pipename.h"
#include "pipebuf.h"
#include "pipecreate.h"
#include "pipesched.h"
#include "pipe-handler.h"
#include "pipedir.h"
/*---------------------------------------------------------------------------
** pipedir.c
** ---------
** This module handles the directory-related requests to the handler.
** The functions contained here are not needed if the compile-time flag
** PIPEDIR is false.
**
** Visible Functions
** -----------------
** void SetPipeDate (pipe)
** void PipeLock (pkt)
** void PipeDupLock (pkt)
** void PipeUnLock (pkt)
** void PipeExamine (pkt)
** void PipeExNext (pkt)
** void InitLock (lock, key)
**
** Macros (in pipedir.h)
** ---------------------
** - none -
**
** Local Functions
** ---------------
** void InitPipedirLock ()
** void FillFIB (fib, DiskKey, FileName, Protection, Type, Size, NumBlocks, Datep)
*/
/*---------------------------------------------------------------------------
** "PipedirLock" is the lock returned by PipeLock() to clients requesting a
** shared lock on the handler. "LockBytes" is used for the storage of the
** lock. InitLock() sets "PipedirLock" to point to the first longword within
** "LockBytes" to ensure longword alignment for BCPL's sake.
*/
static BYTE LockBytes[sizeof (struct FileLock) + 3];
static struct FileLock *PipedirLock = NULL;
/*---------------------------------------------------------------------------
** SetPipeDate() modifies the date field for the pipe sent. If the compile-
** time flag UPDATE_PIPEDATE is true (see pipe-handler.h), the handler's date
** is modified as well.
*/
void SetPipeDate (pipe)
PIPEDATA *pipe;
{ (void) DateStamp (&pipe->accessdate);
#if UPDATE_PIPEDATE
(void) DateStamp (&PipeDate);
#endif UPDATE_PIPEDATE
}
/*---------------------------------------------------------------------------
** PipeLock() responds to Lock requests. Only multiple access locks are
** granted. The same lock is returned to all clients for a given entity.
** Note: the code which checks if the lock sent in the packet relies on
** the fact that the pipe-handler does not allow subdirectories. If a lock
** on a pipe is passed in, then that pipe is opened. Otherwise, the name is
** parsed without reference to the lock.
*/
void PipeLock (pkt)
struct DosPacket *pkt;
{ char *name, *tapname;
ULONG size;
struct FileLock *lock;
PIPEDATA *pipe;
void InitPipedirLock();
InitPipedirLock ();
pkt->dp_Res1= 0; /* error, for now */
pkt->dp_Res2= 0; /* clear for case of no error */
lock= (struct FileLock *) BPTRtoCptr (pkt->dp_Arg1);
if (pkt->dp_Arg3 != SHARED_LOCK)
{ pkt->dp_Res2= ERROR_OBJECT_WRONG_TYPE;
goto PLOCKEXIT;
}
if (! ParsePipeName (BPTRtoCptr (pkt->dp_Arg2), &name, &size, &tapname))
{ pkt->dp_Res2= ERROR_INVALID_COMPONENT_NAME;
goto PLOCKEXIT;
}
if ( (lock == NULL) || ((pipe= (PIPEDATA *) lock->fl_Key) == NULL) )
{ if (name[0] == '\0')
pkt->dp_Res1= CptrtoBPTR (PipedirLock);
else
{ if ((pipe= FindPipe (name)) == NULL)
{ pkt->dp_Res2= ERROR_OBJECT_NOT_FOUND;
goto PLOCKEXIT;
}
pkt->dp_Res1= CptrtoBPTR (pipe->lock);
++pipe->lockct;
}
}
else /* lock sent in packet was on the pipe */
{ if (name[0] != '\0')
{ pkt->dp_Res2= ERROR_INVALID_COMPONENT_NAME;
goto PLOCKEXIT;
}
pkt->dp_Res1= CptrtoBPTR (pipe->lock);
++pipe->lockct;
}
PLOCKEXIT:
ReplyPkt (pkt);
}
/*---------------------------------------------------------------------------
** PipeDupLock() responds to DupLock requests. It is assumed that the lock
** sent is valid. The same lock is returned; the only action taken is to
** increment the lock count if the lock is on an individual pipe. If the
** zero lock is sent, the zero lock is (properly) returned, even though this
** handler should never receive that request. Notice that this routine never
** returns an error.
*/
void PipeDupLock (pkt)
struct DosPacket *pkt;
{ struct FileLock *lock;
PIPEDATA *pipe;
pkt->dp_Res1= pkt->dp_Arg1; /* reuse same structure */
pkt->dp_Res2= 0;
if ((lock= (struct FileLock *) BPTRtoCptr (pkt->dp_Arg1)) != NULL)
{ if ((pipe= (PIPEDATA *) lock->fl_Key) != NULL)
++pipe->lockct; /* lock is on an individual pipe */
}
ReplyPkt (pkt);
}
/*---------------------------------------------------------------------------
** PipeUnLock() responds to UnLock requests.
*/
void PipeUnLock (pkt)
struct DosPacket *pkt;
{ struct FileLock *lock;
PIPEDATA *pipe;
if ((lock= (struct FileLock *) BPTRtoCptr (pkt->dp_Arg1)) == NULL)
{ pkt->dp_Res1= 0;
pkt->dp_Res2= ERROR_INVALID_LOCK;
}
else
{ if ((pipe= (PIPEDATA *) lock->fl_Key) != NULL)
{ --pipe->lockct;
CheckWaiting (pipe); /* will discard if totally unused */
}
pkt->dp_Res1= 1; /* no error */
pkt->dp_Res2= 0;
}
ReplyPkt (pkt);
}
/*---------------------------------------------------------------------------
** PipeExamine() responds to Examine requests. For locks on the handler, the
** address first item of the pipelist is stored in the DiskKey field for
** PipeExNext()'s reference.
*/
void PipeExamine (pkt)
struct DosPacket *pkt;
{ struct FileInfoBlock *fib;
struct FileLock *lock;
PIPEDATA *pipe;
void FillFIB();
pkt->dp_Res1= 1; /* no error, for now */
pkt->dp_Res2= 0;
fib= (struct FileInfoBlock *) BPTRtoCptr (pkt->dp_Arg2);
if ((lock= (struct FileLock *) BPTRtoCptr (pkt->dp_Arg1)) == NULL)
{ pkt->dp_Res1= 0;
pkt->dp_Res2= ERROR_OBJECT_NOT_FOUND;
}
else
{ if ((pipe= (PIPEDATA *) lock->fl_Key) == NULL) /* then this is a lock on the handler */
{ FillFIB ( fib, FirstItem (&pipelist), HandlerName,
(FIBF_EXECUTE | FIBF_DELETE), 1,
0, 0, &PipeDate );
}
else
{ FillFIB ( fib, NULL, pipe->name,
(FIBF_EXECUTE | FIBF_DELETE), -1,
pipe->buf->len, 1, &pipe->accessdate );
}
}
ReplyPkt (pkt);
}
/*---------------------------------------------------------------------------
** PipeExNext() responds to ExNext requests. The DiskKey field of the
** FileInfoBlock is assumed to be a pointer to the next pipe in the pipelist
** which is to be listed in the directory. We then scan pipelist for this
** pointer, and upon finding it, store its information in the FileInfoBlock
** and store the address of the next pipe in pipelist in the DiskKey field.
** If the pipe is not found in the list, or if DiskKey is NULL, then
** ERROR_NO_MORE_ENTRIES is returned.
** By rescanning the list each time, deletion of a pipe cannot hurt us
** by causing a dangling pointer in DiskKey -- we just end the directory
** listing there. This can cause incomplete directory information for the
** cleint, however, if the last listed pipe is deleted before the client's
** next ExNext() call.
*/
void PipeExNext (pkt)
struct DosPacket *pkt;
{ struct FileLock *lock;
struct FileInfoBlock *fib;
PIPEDATA *listitem, *pipe;
void FillFIB();
pkt->dp_Res1= 0; /* error, for now */
if ((lock= (struct FileLock *) BPTRtoCptr (pkt->dp_Arg1)) == NULL)
{ pkt->dp_Res2= ERROR_INVALID_LOCK;
goto EXNEXTREPLY;
}
if (lock->fl_Key != NULL) /* then an individual pipe */
{ pkt->dp_Res2= ERROR_OBJECT_WRONG_TYPE;
goto EXNEXTREPLY;
}
pkt->dp_Res2= ERROR_NO_MORE_ENTRIES; /* until found otherwise */
fib= (struct FileInfoBlock *) BPTRtoCptr (pkt->dp_Arg2);
if ((listitem= (PIPEDATA *) fib->fib_DiskKey) == NULL)
goto EXNEXTREPLY;
for (pipe= (PIPEDATA *) FirstItem (&pipelist); pipe != NULL; pipe= (PIPEDATA *) NextItem (pipe))
if (listitem == pipe)
break;
if (listitem == pipe) /* then found next entry */
{ FillFIB ( fib, NextItem (listitem), listitem->name,
(FIBF_EXECUTE | FIBF_DELETE), -1,
listitem->buf->len, 1, &listitem->accessdate );
pkt->dp_Res1= 1;
pkt->dp_Res2= 0;
}
EXNEXTREPLY:
ReplyPkt (pkt);
}
/*---------------------------------------------------------------------------
** PipeParentDir() responds to ParentDir requests.
*/
void PipeParentDir (pkt)
struct DosPacket *pkt;
{ struct FileLock *lock;
void InitPipedirLock();
InitPipedirLock ();
pkt->dp_Res2= 0;
if ((lock= (struct FileLock *) BPTRtoCptr (pkt->dp_Arg1)) == NULL)
{ pkt->dp_Res1= 0;
pkt->dp_Res2= ERROR_INVALID_LOCK;
}
else
{ if (lock->fl_Key == NULL) /* then lock is on handler */
pkt->dp_Res1= 0; /* root of current filing system */
else
pkt->dp_Res1= CptrtoBPTR (PipedirLock);
}
ReplyPkt (pkt);
}
/*---------------------------------------------------------------------------
*/
static void InitPipedirLock ()
{ if (PipedirLock == NULL)
{ PipedirLock= (struct FileLock *) (((ULONG) LockBytes + 3) & ((~0)<<2));
InitLock (PipedirLock, NULL);
}
}
/*---------------------------------------------------------------------------
** InitLock() initializes locks returned to clients by PipeLock(). For locks
** on individual pipes, the "fl_Key" field points to the associated pipe's
** PIPEDATA structure. For the handler, the "fl_Key" field is NULL.
*/
void InitLock (lock, key)
struct FileLock *lock;
LONG key;
{ lock->fl_Link= 0;
lock->fl_Key= key;
lock->fl_Access= SHARED_LOCK; /* only mode allowed */
lock->fl_Task= PipePort; /* set during handler init */
lock->fl_Volume= CptrtoBPTR (DevNode); /* also set during init */
}
/*---------------------------------------------------------------------------
** FillFIB() fills a FileInfoBlock with the specified information. Note
** that handlers must store BSTR's in the FileInfoBlock.
*/
static void FillFIB (fib, DiskKey, FileName, Protection, Type, Size, NumBlocks, Datep)
struct FileInfoBlock *fib;
LONG DiskKey;
char *FileName; /* null-terminated */
LONG Protection;
LONG Type;
LONG Size;
LONG NumBlocks;
struct DateStamp *Datep;
{ fib->fib_DiskKey= DiskKey;
fib->fib_DirEntryType= Type;
CstrtoBSTR (FileName, fib->fib_FileName, sizeof (fib->fib_FileName));
fib->fib_Protection= Protection;
fib->fib_EntryType= Type; /* ??? */
fib->fib_Size= Size;
fib->fib_NumBlocks= NumBlocks;
CopyMem (Datep, &fib->fib_Date, sizeof (struct DateStamp));
fib->fib_Comment[0]= '\0'; /* empty BSTR */
}